package pl.edu.mimuw.mas.agent.behaviour;

import jade.content.lang.Codec.CodecException;
import jade.content.onto.OntologyException;
import jade.content.onto.UngroundedException;
import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Zachowanie będące serwerem. Odbiera wiadomości, tworzy dopowiedź. Odpowiedź
 * jest wypełniana w abstrakcyjnej metodzie <code>doAction</code>.
 */
public abstract class ServerBehaviour extends Behaviour {
	private static final long serialVersionUID = -2546169388899356380L;
	private final Logger log = LoggerFactory.getLogger(getClass());
	
	private MessageTemplate mt = null;
	private boolean finished = false;
	
	public ServerBehaviour(Agent agent) {
		super(agent);
	}
	
	public abstract boolean doAction(ACLMessage msg, ACLMessage reply) throws UngroundedException, CodecException, OntologyException, UnreadableException, IOException;
	
	@Override
	public void action() {
		ACLMessage msg;
		if (mt != null) {
			msg = myAgent.receive(mt);
		} else {
			msg = myAgent.receive();
		}
		if (msg != null) {
			
			if (log.isTraceEnabled()) {
				log.trace("{} <-\n {}", myAgent.getName(), msg.toString());				
			}
			
			ACLMessage reply = msg.createReply();
			try {
				if(doAction(msg, reply)) {
					myAgent.send(reply);		
				}
			} catch (UngroundedException e) {
				log.error("{} : UngroundedException {}", myAgent.getName(), e);
				reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
				myAgent.send(reply);
			} catch (CodecException e) {
				log.error("{} : CodecException {}", myAgent.getName(), e);
				reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
				myAgent.send(reply);
			} catch (OntologyException e) {
				log.error("{} : OntologyException {}", myAgent.getName(), e);
				reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
				myAgent.send(reply);
			} catch (Exception e) {
				log.error("{} : ?!? Exception {}", myAgent.getName(), e);
				e.printStackTrace();
				reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
				myAgent.send(reply);
			}			
			
			if (log.isTraceEnabled()) {
				log.trace("{} ->\n {}", myAgent.getName(), reply.toString());				
			}
			
		} else {
			block();
		}
	}
	
	public final boolean done() {
		return finished;
	}
	
	public void stop() {
		finished = true;
	}
	
	public void setMessageTemplate(MessageTemplate mt) {
		this.mt = mt;
	}
}
